0300. 最长递增子序列【中等】
1. 📝 题目描述
给你一个整数数组 nums,找到其中最长严格递增子序列的长度。
子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
子序列 是可以通过从另一个数组删除或不删除某些元素,但不更改其余元素的顺序得到的数组。
示例 1:
txt
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4。1
2
3
2
3
示例 2:
txt
输入:nums = [0,1,0,3,2,3]
输出:41
2
2
示例 3:
txt
输入:nums = [7,7,7,7,7,7,7]
输出:11
2
2
提示:
1 <= nums.length <= 2500-10^4 <= nums[i] <= 10^4
进阶:
- 你能将算法的时间复杂度降低到
O(n log(n))吗?
2. 🎯 s.1 - 贪心 + 二分
c
int lengthOfLIS(int* nums, int numsSize) {
int* tails = (int*)malloc(sizeof(int) * numsSize);
int size = 0;
for (int i = 0; i < numsSize; i++) {
int lo = 0, hi = size;
while (lo < hi) {
int mid = lo + (hi - lo) / 2;
if (tails[mid] < nums[i]) lo = mid + 1;
else hi = mid;
}
tails[lo] = nums[i];
if (lo == size) size++;
}
free(tails);
return size;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
js
/**
* @param {number[]} nums
* @return {number}
*/
var lengthOfLIS = function (nums) {
// 贪心 + 二分
const tails = []
for (const num of nums) {
let lo = 0,
hi = tails.length
while (lo < hi) {
const mid = (lo + hi) >> 1
if (tails[mid] < num) lo = mid + 1
else hi = mid
}
tails[lo] = num
}
return tails.length
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
py
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
tails = []
for num in nums:
lo, hi = 0, len(tails)
while lo < hi:
mid = (lo + hi) // 2
if tails[mid] < num:
lo = mid + 1
else:
hi = mid
if lo == len(tails):
tails.append(num)
else:
tails[lo] = num
return len(tails)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- 时间复杂度:
,其中 是数组长度 - 空间复杂度:
,tails数组
算法思路:
- 维护一个
tails数组,tails[i]表示长度为 的递增子序列的最小末尾元素 - 对每个元素二分查找其在
tails中的插入位置,更新或追加